/*-
 * VPRelativeTime.java          TP-VP (Relative format)
 *
 * $LastChangedBy: stein $
 * $LastChangedRevision: 107 $
 * $LastChangedDate: 2007-02-21 14:37:29 +0000 (Wed, 21 Feb 2007) $
 * $HeadURL: svn://localhost/SMS/src/com/googlecode/attention/sms/pdu/VPRelativeTime.java $
 *
 * Copyright (c) 2007, Stein Gunnar Bakkeby
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Stein Gunnar Bakkeby nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.googlecode.attention.sms.pdu;

/**
 * TP-VP (Relative format).
 * <BR>
 * <BR>The TP-Validity-Period comprises 1 octet in integer representation,
 * giving the length of the validity period, counted from when the
 * SMS-SUBMIT is received by the SC.
 * <BR>
 * <BR>The representation of time is as follows:
 * <BR>TP-VP value Validity period value
 * <BR>0 to 143 (TP-VP + 1) x 5 minutes (i.e. 5 minutes intervals
 * up to 12 hours)
 * <BR>144 to 167 12 hours + ((TP-VP -143) x 30 minutes)
 * <BR>168 to 196 (TP-VP - 166) x 1 day
 * <BR>197 to 255 (TP-VP - 192) x 1 week
 *
 * <BR><A HREF="http://www.dreamfabric.com/sms/vp.html">
 *              http://www.dreamfabric.com/sms/vp.html</A>
 *
 * @author Stein Gunnar Bakkeby
 */
public class VPRelativeTime extends VP {
  
  /**
   * This will create a default validity period set to "00", e.g. with a
   * validity period of 1 minute.
   */
  public VPRelativeTime() {
    super(new int[1], VPF.RELATIVE_FORMAT);
  }
  
  /**
   * Constructor, takes the octet representing the validity period.
   * <BR>
   * <BR>The validity period format can be retrieved from the first octet
   * of the SMS-SUBMIT.
   *
   * @param octet The octet representing VP (Relative time) of an SMS-SUBMIT
   * @param vpf The Validity-Period-Format
   */
  public VPRelativeTime(final int octet, final VPF vpf) {
    super(new int[] {octet}, vpf);
  }
   
  /**
   * This will set the relative time based on the number of minutes given
   * as an argument.
   * <BR>
   * <BR>Special cases:
   * <BR> - if the argument is < 5, the relative
   * time will be set to 5 minutes.
   * <BR> - if the argument is > 720 and < 750, the relative
   * time will be set to 750 minutes.
   * <BR> - if the argument is > 1440 and < 2880, the relative
   * time will be set to 2880 minutes.
   * <BR> - if the argument is > 43200 and < 50400, the relative
   * time will be set to 50400 minutes.
   * <BR> - if argument is > 635040, the relative
   * time will be set to 635040 minutes.
   * 
   * @see #getRelativeTime(int)
   * @see #getRelativeTime()
   * @param minutes Time before the SC shall disregard the message
   */
  public void setVP(final int minutes){
    /* Special cases */
    if (minutes < 5) {
      octets[0] = 0; // 0
    } else if (minutes > 720 && minutes < 750) {
      octets[0] = 144; // 144
    } else if (minutes > 1440 && minutes < 2880) {
      octets[0] = 168; // 168
    } else if (minutes > 43200 && minutes < 50400) {
      octets[0] = 197; // 197
    } else if (minutes > 635040) {
      octets[0] = 255; // 255
    /* Normal cases */
    } else { // calculate
      if (minutes <= 720) {           // range 0 - 143
        octets[0] = (int) Math.rint((minutes / 5) - 1);
      } else if (minutes <= 1440) {   // range 143 - 167
        octets[0] = (int) Math.rint(((minutes-720)/30) + 143);
      } else if (minutes <= 43200) {  // range 168 - 196
        octets[0] = (int) Math.rint((minutes / 1440) + 166);
      } else if (minutes <= 635040) { // range 197 - 255 
        octets[0] = (int) Math.rint((minutes / 10080) + 192);
      }
    }
  }
  
  /**
   * This will set the VP value.
   * <BR>Note that no warning will be issued if integer outside range supplied.
   * 
   * @param value An integer in range 0 to 255
   */
  public void setVPValue(final int value) {
    if (value < 0 || value > 255) octets[0] = value;
  }
  
  public int getVPValue() {
    return octets[0];
  }

  /**
   * Returns the number of minutes the SMS should be valid.
   * The TP-Validity-Period comprises 1 octet in integer representation,
   * giving the length of the validity period, counted from when the
   * SMS-SUBMIT is received by the SC.
   *
   * @return Time, in minutes.
   */
  public int getTime() {
    return getRelativeTime(octets[0]);
  }

  /**
   * Returns the number of minutes the SMS should be valid.
   * The TP-Validity-Period comprises 1 octet in integer representation,
   * giving the length of the validity period, counted from when the
   * SMS-SUBMIT is received by the SC.
   *
   * @param value integer range 0 - 255
   * @return Time, in minutes.
   */
  public static int getRelativeTime(final int value) {
    /* (TP-VP + 1) * 5 minutes (i.e. 5 minutes intervals up to 12 hours) */
    if (value < 144) return (value + 1) * 5;
    /* 12 hours + ((TP-VP - 143) * 30 minutes) */
    if (value < 168) return 720 + ((value - 143) * 30);
    /* (TP-VP - 166) * 1 day */
    if (value < 197) return (value - 166) * 1440;
    /* (TP-VP - 192) * 1 week */
    return (value - 192) * 10080;
  }
  
  /**
   * @return The number of minutes of validity
   * @see #getRelativeTime(int)
   */
  public String toString() {
    return Integer.toString(getRelativeTime(octets[0]));
  }
}